import { expect } from 'chai';
import * as sinon from 'sinon';
import * as inputCheck from '../src/input-check'
import * as step from '@flow-step/step-toolkit'
import path from 'path'
import mdFile from 'md5-file'
import proxyquire from 'proxyquire'

describe('getUploadInputs', () => {
    let sandbox: sinon.SinonSandbox;
    let getInputsStub: sinon.SinonStub;
    let md5SyncStub: sinon.SinonStub;
    let fsStub: { statSync: sinon.SinonStub; }


    beforeEach(() => {
        sandbox = sinon.createSandbox();
        getInputsStub = sandbox.stub(inputCheck, 'getInputs');
        md5SyncStub = sandbox.stub(mdFile, 'sync');
        fsStub = {
            statSync: sandbox.stub(),
        }
    });

    afterEach(() => {
        sandbox.restore();
    });

    it('should return correct input with fileMD5 and artifactFullName', async () => {
        const mockInput = {
            artifactPath: '/path/to/artifact',
            artifactName: 'file.txt'
        };
        const mockFileMD5 = 'abc123';

        getInputsStub.resolves(mockInput);
        md5SyncStub.returns(mockFileMD5);

        fsStub.statSync.returns({
            isDirectory: () => false
        });

        const getUploadInputsProxy = proxyquire('../src/execute-step', {
            fs: fsStub,
        }).getUploadInputs;

        const result = await getUploadInputsProxy();
        expect(result).to.deep.equal({
            ...mockInput,
            fileMD5: mockFileMD5,
            artifactFullName: path.join(mockInput.artifactPath, mockInput.artifactName)
        });

    });

    it('should throw error if artifactFullName is a directory', async () => {
        const mockInput = {
            artifactPath: '/path/to/artifact',
            artifactName: 'directory'
        };
        getInputsStub.resolves(mockInput);
        fsStub.statSync.returns({
            isDirectory: () => true
        });

        const getUploadInputsProxy = proxyquire('../src/execute-step', {
            fs: fsStub,
        }).getUploadInputs;

        try{
            const result = await getUploadInputsProxy();
            expect.fail('Expected an error to be thrown');
        }catch (e:any){
            expect(e.message).to.include('should refer to a file, not directory')

        }
    });

    it('should throw error if fsPromises.stat fails', async () => {
        const mockInput = {
            artifactPath: '/path/to/artifact',
            artifactName: 'directory'
        };
        getInputsStub.resolves(mockInput);
        const error = new Error('Failed to stat file');
        fsStub.statSync.throws(error);

        const getUploadInputsProxy = proxyquire('../src/execute-step', {
            fs: fsStub,
        }).getUploadInputs;

        try{
            const result = await getUploadInputsProxy();
            expect.fail('Expected an error to be thrown');
        }catch (e:any){
            expect(e.message).to.equal('Failed to stat file')

        }
    });
});
